package com.sticktogether.pushnotifications;

import static com.sticktogether.pushnotifications.CommonUtilities.SENDER_ID;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.BigTextStyle;
import android.support.v4.app.TaskStackBuilder;

import com.google.android.gcm.GCMBaseIntentService;
import com.sticktogether.R;
import com.sticktogether.ShowANewPinOnMap;
import com.sticktogether.server.ServerCommunication;
import com.sticktogether.services.StickTogether;
import com.sticktogether.usermanagement.Member;

public class GCMIntentService extends GCMBaseIntentService {
   
	public static LocationManager mlocManager;
	public static LocationListener mlocListener;
	
	public GCMIntentService() {
        super(SENDER_ID);
    }

    /**
     * Method called on device registered
     */
    @Override
    protected void onRegistered(Context context, String registrationId) {
        Register.registeronserver();
    }

    /**
     * Method called on device un registred
     */
    @Override
    protected void onUnregistered(Context context, String registrationId) {
        // device unregistered
    }

    /**
     * This method is called when a GCM is received.
     * This could have several reasons:
     * - A notification from the server that should be displayed.
     * - A user has changed his position, so update it.
     * - A marker has been added / changed / removed, so reload all markers
     */
    @Override
    protected void onMessage(Context context, Intent intent) {
        // all possible Strings that MIGHT have been set by the server when sending the message
    	String postid = intent.getExtras().getString("postid");
        String topicid = intent.getExtras().getString("topicid");
        String title = intent.getExtras().getString("title");
        String posttext = intent.getExtras().getString("posttext");
        String albumtitle = intent.getExtras().getString("albumtitle");
        String poster = intent.getExtras().getString("poster");
        String shoutbox = intent.getExtras().getString("shoutbox");
        String fabi = intent.getExtras().getString("fabi");
        String userid = intent.getExtras().getString("userid");
        String latitude = intent.getExtras().getString("x");
        String longitude = intent.getExtras().getString("y");
        String updatemarkers = intent.getExtras().getString("updatemarkers");
        
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
        
        // A user has changed his position, so find him on the map and update his marker
        if(userid!=null && latitude != null && longitude!=null) {
        	int id = Integer.parseInt(userid);
        	Member member = ServerCommunication.members.get(id);
        	if(member!=null) {
    			member.setLocation(Double.parseDouble((latitude)), Double.parseDouble(longitude));
    			member.setLastUpdateTime(poster);
        	}
        	// There was no member on the map that we could update, so completly refresh all members
        	else {
        		// getMemberListFromServer() updates all markers if possible. If not it returns false
        		if(!ServerCommunication.getMemberListFromServer()) {
        			// We have received a GCM message about a changed position, but the app is not running.
        			// So it seems like it has been killed without being able to unregister from those calls in onPause().
        			// So we unregister now!
        			ServerCommunication.ReceivePositionUpdates(context, false);
        		}
        	}
        }
        // A marker has been added / changed or removed, so update all markers
        else if (updatemarkers != null) {
    		// getPinListFromServer() updates all pins if possible. If not it returns false
        	ServerCommunication.getPinListFromServer();
        	
        	// show a notification if the marker was added (and not moved or deleted)
        	 if(title != null && poster != null) {
        		 if(sharedPref.getBoolean("notifications_new_message", true)) {
 					Intent resultIntent = new Intent(context,ShowANewPinOnMap.class);
 					String text = String.format(context.getString(R.string.new_marker_by),poster);
 					String ticker = String.format(context.getString(R.string.new_marker), title, poster);
 					resultIntent.putExtra("showThisPinOnMap", title);
 					generateNotification(context, (int) (Integer.MAX_VALUE/2 + (Math.random()*(Integer.MAX_VALUE/2 - 10))), resultIntent, title, text, ticker, R.drawable.ic_launcher, null, true);
        		 }
        	 }
        }
        
        // OK, then it must have been a notification we want to display, so first let's have a look if notifications are enabled in the preferences.
        else if(sharedPref.getBoolean("notifications_new_message", true)) {
	       
        	// display a "new post in forum" notification
        	if(postid!=null && title != null && poster != null && topicid != null) {
		        String url = "http://www.wirhassenalledenjul.de/viewtopic.php?p=" + postid + "&last=1#" + postid;
		        String text = String.format(context.getString(R.string.last_poster),poster);
		        String ticker = String.format(context.getString(R.string.new_post), title, poster);
		        
		        // notifies user
		        generateNotification(context, Integer.parseInt(topicid), url, title, text, ticker, posttext);
		        ServerCommunication.updateNotificationTable(postid, topicid, context);
	        }
        	
        	// display a "new post in shoutbox" notification
	        else if(shoutbox!=null && poster!=null) {
	        	
	        	title = "Shoutbox";
	        	String text = String.format(context.getString(R.string.last_poster),poster);
	        	String ticker = String.format(context.getString(R.string.new_shout), poster);
	        	
	        	// notifies user
	        	generateNotification(context, 0, "http://www.wirhassenalledenjul.de/portal.php#shoutbox", title, text, ticker, posttext);
	        }
        	
        	// display a "new comment on pic in gallery" notification
	        else if(postid != null && albumtitle != null && poster != null) {
		        String url = "http://www.wirhassenalledenjul.de/fotos/displayimage.php?pid=" + postid;
		        String text = String.format(context.getString(R.string.new_imagecomment),poster);
		        title = String.format( "%s", albumtitle);
		        String ticker = String.format(context.getString(R.string.new_imagecomment),poster);
		        
		        // notifies user
		        generateNotification(context, Integer.MAX_VALUE / 3 + Integer.parseInt(postid), url, title, text, ticker, posttext);
	        }
        	
        	// OK we have got a message we could not identify, so ask the user if he has installed the latest version of the app
        	// when he clicks on the notification he is directed directly to the application in the play store
	        else if(fabi==null){
	        	String url = "market://details?id=com.sticktogether";
		        String text = context.getString(R.string.check_version);
		        title = context.getString(R.string.unnokwn_notification);
		        String ticker = context.getString(R.string.unnokwn_notification_explan);
		        
	        	// notifies user
	        	generateNotification(context, 1, url,  title, text, ticker, null);
	        }
        }
        
        // It was a message that was manually sent from the administrator-user interface (index.php on server in the folder /android/)
        // Display this message (also if notifications have been disabled)
        if(fabi!=null) {
        	// notifies user
        	if(title.equals("loc")) {
    			Intent Serviceintent = new Intent(this, StickTogether.class);
    			startService(Serviceintent);
        	}
        	else {
	        	title = (!title.equals("")) ? title : context.getString(R.string.app_name);
	        	generateNotification(context, -((int) (Math.random()*(Integer.MAX_VALUE-10) + 5)), "http://www.wirhassenalledenjul.de", title, fabi, fabi, fabi);
        	}
        }
    }

    /**
     * Method called on receiving a deleted message
     */
    @Override
    protected void onDeletedMessages(Context context, int total) {
        // Received deleted messages notification
    }

    /**
     * Method called on Error
     */
    @Override
    public void onError(Context context, String errorId) {
        // received error with code errorId
    }

    /**
     * Method called on recoverable Error
     */
    @Override
    protected boolean onRecoverableError(Context context, String errorId) { 
        return super.onRecoverableError(context, errorId);
    }

    
    /**
     * This method displays a notification in the status bar
     * 
     * @param context
     * @param id:		the id we want the notification to use (for later reference, or for overwriting notifications)
     * @param url:		the url that should be opened after the notification was clicked.
     * @param title:	title of the notfifiaciton
     * @param text:		text of the notification
     * @param ticker	text of the ticker
     */
    private static void generateNotification(Context context, int id, String url, String title, String text, String ticker, String bigText ) {
    	Intent resultIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
    	generateNotification(context, id, resultIntent, title, text, ticker, R.drawable.notification_icon, bigText, true );
    }
    
    public static void generateNotification(Context context, int id, Intent resultIntent, String title, String text, String ticker, int icon, String bigText, boolean autocancel ) {

    	SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);

    	long[] vibratePattern;
    	if(!sharedPref.getBoolean("notifications_new_message_vibrate", true)) {
    		vibratePattern = new long[] {0};
    	}
    	else {
    		int vibrate_id = Integer.parseInt(sharedPref.getString("vibrate_pattern", "2"));
    		vibratePattern = getVibratePattern(vibrate_id);
    	}
    	int led = Integer.parseInt(sharedPref.getString("led_color", "-1"));

        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(context)
        		.setContentTitle(title)
        		.setContentText(text)
        		.setTicker(ticker)
        		.setLights(led, 500, 500)
                .setSmallIcon(icon)
        		.setAutoCancel(autocancel)
        		.setVibrate(vibratePattern)
        		.setSound(Uri.parse(sharedPref.getString("notifications_new_message_ringtone", "")));
        
        if(bigText != null) {
	        BigTextStyle bigStyle = new NotificationCompat.BigTextStyle();
	        bigStyle.setSummaryText(text);
	        bigStyle.bigText(bigText);
	        mBuilder.setStyle(bigStyle);
        }

        // The stack builder object will contain an artificial back stack for the
        // started Activity.
        // This ensures that navigating backward from the Activity leads out of
        // your application to the Home screen.
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);

        // Adds the Intent that starts the Activity to the top of the stack
        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent =
                stackBuilder.getPendingIntent(
                    id,
                    PendingIntent.FLAG_UPDATE_CURRENT
                );
        mBuilder.setContentIntent(resultPendingIntent);
        NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        mNotificationManager.notify(id, mBuilder.build());

    }
    
    /**
     * Here I have created some funny vibration patterns that can be chosen in the preference activity
     * To get one of them, we call this method.
     * 
     * @param vibrate_id: Id of the pattern we want to get
     * @return: the vibration pattern we wanted to have
     */
    public static long[] getVibratePattern(int vibrate_id) {
    	long[] vibratePattern;
    	switch(vibrate_id) {
			case 1: vibratePattern = new long[] {0, 200, 1000}; break;
			case 2: vibratePattern = new long[] {0, 200, 200, 200, 1000}; break;
			case 3: vibratePattern = new long[] {0, 200, 200, 200, 200, 200, 1000}; break;
			case 4: vibratePattern = new long[] {0, 500, 1000}; break;
			case 5: vibratePattern = new long[] {0, 500, 500, 500, 1000}; break;
			case 6: vibratePattern = new long[] {0, 500, 500, 500, 500, 500, 1000}; break;
			case 7: vibratePattern = new long[] {0,200,200,200,200,200,500,500,200,500,200,500,500,200,200,200,200,200,1000}; break;
			default: vibratePattern = new long[] {0, 200, 200, 200, 1000}; break;
		}
    	return vibratePattern;
    }

}
